package com.editso.haier.storage;

import com.editso.haier.util.Utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.servlet.ServletContext;
import java.io.*;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
/**
 * 本地存储
 * */
@ConditionalOnExpression(value = "'${haier.resource-storage-type:local}' == 'local'")
@Component
public class LocalStorage implements Storage{

    @Value("${haier.local-storage-root-path:default}")
    private String root;

    @Value("${haier.storage-head:storage}")
    private String storageHead;

    private ServletContext context;

    @Autowired
    public void setContext(ServletContext context) {
        this.context = context;
    }

    @PostConstruct
    private void created(){
        System.out.println(this);
    }

    /**
     * 存储名称
     */
    @Override
    public String getName() {
        return this.getClass().getSimpleName();
    }

    @Override
    public URI getUri() {
        if (root == null || "default".endsWith(root))
            root = context.getRealPath("/");
        if (! root.startsWith(File.separator))
            root = context.getRealPath(root);
        return URI.create(String.format("%s:%s://%s", storageHead, getScheme(), root));
    }

    @Override
    public URI getRelPath(String path) {
        URI relPath = Storage.super.getRelPath(path);
        return URI.create(relPath.getRawSchemeSpecificPart());
    }

    @Override
    public String getScheme() {
        return "file";
    }

    @Override
    public String save(String path, String fileName, InputStream stream, String contentType) throws IOException {
        File file = openDirectory(path);
        file = new File(file, fileName);
        if (! file.exists() && !file.createNewFile())
            throw new IOException(fileName);
        FileOutputStream outputStream = new FileOutputStream(file);
        Utils.streamWrite(outputStream, stream);
        outputStream.close();
        return fileName;
    }

    @Override
    public FileItem get(String path, String fileName) throws FileNotFoundException{
        return new LocalFileItem(new File(getRelPath(Utils.joinPath(path, fileName))));
    }

    @Override
    public boolean delete(String path, String fileName) {
        return false;
    }

    @Override
    public boolean update(String path, String fileName, InputStream stream) {
        return false;
    }

    @Override
    public boolean exists(String path, String fileName) {
        return new File(getRelPath(Utils.joinPath(path, fileName))).exists();
    }

    public File openDirectory(String name)throws IOException{
        File file = new File(getRelPath(name));
        if (!file.exists() && !file.mkdirs())
            throw new IOException(name);
        if (!file.isDirectory())
            throw new IOException("不是一个目录: " + name);
        return file;
    }

    public InputStream openFile(String path, String fileName)throws FileNotFoundException{
        String file = null;
        if (path == null){
            file = fileName;
        }else {
            if (path.endsWith(File.separator)){
                path = path.substring(path.length() - 1);
            }
            file = String.format("%s%s%s", path, File.separator, fileName);
        }
        return new FileInputStream(new File(file));
    }

    @Override
    public List<FileItem> fileList(String path) throws IOException{
        File directory = openDirectory(path);
        File[] files = directory.listFiles();
        if (files == null) throw new IOException();
        List<FileItem> fileItems = new ArrayList<>();
        for (File file : files) {
            fileItems.add(new LocalFileItem(file));
        }
        return fileItems;
    }

    public  static class LocalFileItem implements FileItem{
        private final File file;

        public LocalFileItem(File file) {
            this.file = file;
        }

        @Override
        public boolean isDirectory() {
            return file.isDirectory();
        }

        @Override
        public boolean isFile() {
            return file.isFile();
        }

        @Override
        public String getName() {
            return file.getName();
        }

        @Override
        public String getPath() {
            return file.getPath();
        }

        @Override
        public String getContentType() {
            return null;
        }

        @Override
        public long getLength() {
            return file.length();
        }

        @Override
        public InputStream stream() throws FileNotFoundException {
            return new FileInputStream(file);
        }
    }
}
